package com.abe.mvp.model;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;

import com.abe.app.ManagerAPP;
import com.abe.mvp.contact.SerialPortContact;
import com.abe.mvp.model.bean.SerialPortDataBean;
import com.abe.threadmill.R;
import com.abe.utils.NormalUtils;
import com.abe.utils.ThreadPoolUtils;

public class SerialPortModelImp implements SerialPortContact.Model {
	private static SerialPortModelImp serialPortModelImp;
	private static ISerialPortBack serialPortCallBack;
	/** code标识 */
	/** 错误 */
	public static final int CODE_ERROR = 0x001;
	/** 串口开启成功 */
	public static final int CODE_OPEN_SUCCESS = 0x002;
	/** 串口开启失败 */
	public static final int CODE_CLOSE_SUCCESS = 0x003;
	/** 下发命令成功 */
	public static final int CODE_SEND_DATA_SUCCESS = 0x004;
	/** 数据接收成功 */
	public static final int CODE_RECEIVE_DATA_SUCCESS = 0x005;
	/** 数据通道 */
	private OutputStream mOutputStream;
	private InputStream mInputStream;
	/** 操作线程 */
	private ReadThread mReadThread;
	private int type;

	private SerialPortModelImp() {
	}

	/**
	 * @param callback
	 * @return SerialPortModelImp
	 */
	public static SerialPortModelImp from(ISerialPortBack callback) {
		serialPortCallBack = callback;
		if (serialPortModelImp == null) {
			synchronized (SerialPortModelImp.class) {
				if (serialPortModelImp == null)
					serialPortModelImp = new SerialPortModelImp();
			}
		}
		return serialPortModelImp;
	}

	@Override
	public void openSerialPort(int type) {
		try {
			this.type = type;
			if (ManagerAPP.getInstance().getSerialPort(type) != null) {
				mInputStream = ManagerAPP.getInstance().getSerialPort(type)
						.getInputStream();
				mOutputStream = ManagerAPP.getInstance().getSerialPort(type)
						.getOutputStream();
				/** 串口开启成功 */
				serialPortCallBack.onResult(CODE_OPEN_SUCCESS, null, null);
				/** 开启读数据等待 */
				mReadThread = new ReadThread();
				mReadThread.start();
			} else {
				serialPortCallBack.onResult(CODE_ERROR, null,
						NormalUtils.getString(R.string.serialport_open_error));
			}
		} catch (InvalidParameterException e) {
			e.printStackTrace();
			serialPortCallBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.serialport_open_error));
		} catch (SecurityException e) {
			e.printStackTrace();
			serialPortCallBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.serialport_open_error));
		} catch (IOException e) {
			e.printStackTrace();
			serialPortCallBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.serialport_open_error));
		}

	}

	@SuppressWarnings("static-access")
	@Override
	public void sendCommand(byte[] buffer) {
		if (mOutputStream != null) {
			if (buffer != null) {
				try {
					mOutputStream.write(buffer);
					ManagerAPP.TXT.writeTxtFile(new String(buffer));
					serialPortCallBack.onResult(CODE_SEND_DATA_SUCCESS, null,
							null);
					// receiveData();
				} catch (IOException e) {
					e.printStackTrace();
					serialPortCallBack.onResult(CODE_ERROR, null, NormalUtils
							.getString(R.string.serialport_send_error));
				}
			} else {
				serialPortCallBack.onResult(CODE_ERROR, null,
						"Command data null ");
			}
		} else {
			serialPortCallBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.serialport_open_error));
		}
	}

	@SuppressWarnings("unused")
	private void receiveData() {
		ThreadPoolUtils.execute(new ReadThread2());
	}

	@Override
	public void closeSerialPort() {
		if (mReadThread != null) {
			mReadThread.interrupt();
		}
		try {
			if (mInputStream != null) {
				mInputStream.close();
				mInputStream = null;
			}
			if (mOutputStream != null) {
				mOutputStream.close();
				mOutputStream = null;
			}
			if (ManagerAPP.getInstance().getSerialPort(type) != null) {
				ManagerAPP.getInstance().closeSerialPort(type);
			}
			/** 串口关闭成功 */
			serialPortCallBack.onResult(CODE_CLOSE_SUCCESS, null, null);
		} catch (IOException e) {
			e.printStackTrace();
			serialPortCallBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.serialport_close_error));
		}

	}

	private class ReadThread2 implements Runnable {

		@Override
		public void run() {
			try {
				Thread.sleep(120);
				int size;
				byte[] buffer = new byte[64];
				if (mInputStream == null)
					return;
				size = mInputStream.read(buffer);

				if (size > 0) {
					serialPortCallBack.onResult(CODE_RECEIVE_DATA_SUCCESS,
							new SerialPortDataBean(buffer, size), null);
				}
			} catch (IOException e) {
				e.printStackTrace();
				return;
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		}
	}

	private class ReadThread extends Thread {

		@Override
		public void run() {
			super.run();
			while (!isInterrupted()) {
				int size;
				try {
					byte[] buffer = new byte[64];
					if (mInputStream == null)
						return;
					size = mInputStream.read(buffer);

					if (size > 0) {
						serialPortCallBack.onResult(CODE_RECEIVE_DATA_SUCCESS,
								new SerialPortDataBean(buffer, size), null);
					}
				} catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
		}
	}

	/** 将16进制byte[]转化为相应字符串 */
	public static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder();
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

}
